{\rtf0\ansi{\fonttbl\f0\fmodern Courier;\f1\ftech Symbol;\f2\fmodern Ohlfs;}
\margl40
\margr40
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc0\cf0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//
\i 	
\b FILENAME
\b0 :	
\b\i0 eText.PlainText.m \

\b0 //
\i 	
\b SUMMARY
\b0 :	
\b\i0 Implementation of PlainText markup formats of eText (ASCII, C)
\b0 \
//	
\b\i CATEGORY
\b0 :
\i0 	
\b PlainText
\b0 \
//	
\b\i PROTOCOLS
\b0 :
\i0 	
\b <ASCIISupport>
\b0 , 
\b <CSupport>
\b0 \
//	
\b\i INTERFACE
\b0 :
\i0 	
\b None
\b0 \
//	
\b\i AUTHOR
\b0 :		
\b\i0 Rohit Khare
\b0 \
//	
\b\i COPYRIGHT
\b0 :	
\f1\i0 с
\f0\b 1993,94 California Institure of Technology, eText Project\

\b0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i Implementation Comments
\b0\i0 \
//		These methods are pretty much syntactic sugar.\
//		I can't decide whether 'C' should unravel 8-bit characters into ascii\
//	equivalents. OTOH, who programs with ligatures? -- and if they do, leave\
//	it alone!\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b\i History
\b0\i0 \
//	10/17/94:	
\b Cleaned up for eText5.
\b0 \
//	08/05/94:	
\b Completely Rearchitected for 5.0. RK
\b0 \
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Imported Interfaces
\b0 \
//\
	#import "
\b eText.PlainText.h
\b0 "\
\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Encoder API
\b0 \
//\
void 
\b ASCIIEncoder
\b0 (NXStream *
\b s
\b0 , unsigned char *
\b item
\b0 , int 
\b len
\b0 ) \{\
	int i; char *out;\
	\
	if(
\b !len
\b0 ) 
\b len
\b0 =
\b strlen
\b0 ((unsigned char*)
\b item
\b0 );\
	for (i=0; i<len; i++) \{		\
		
\b out
\b0  = 
\b NXToAscii
\b0 (item[i]);\
		
\b NXWrite
\b0 (s, 
\b out
\b0 , 
\b strlen
\b0 (
\b out
\b0 ));\
	\}\
\}\
\

\i @implementation eText(PlainText)\

\i0 //ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Path Operators\

\b0 //\
- 
\b readASCIIfromPath
\b0 :(const char *)path \{\
	NXStream *memstream;\
	\
	
\b memstream
\b0  = 
\b NXMapFile
\b0 (
\b path
\b0 , NX_READONLY);\
	if (memstream)\{\
		[self 
\b readASCII
\b0 : 
\b memstream
\b0 ];\
		NXCloseMemory(memstream, NX_FREEBUFFER);\
	\} else\
		
\b return
\b0  
\b nil
\b0 ;\
	return self;\
\}\
- 
\b writeASCIItoPath
\b0 :(const char *)path \{\
	NXStream *memstream;\
	\
	
\b memstream
\b0  = 
\b NXOpenMemory
\b0 (
\b NULL
\b0 , 0, NX_WRITEONLY);\
	if (memstream) \{\
		[self 
\b writeASCII
\b0 :
\b memstream
\b0 ];\
		
\b NXSaveToFile
\b0 (memstream, 
\b path
\b0 );\
		
\b NXCloseMemory
\b0 (
\b memstream
\b0 , NX_FREEBUFFER);\
	\} else\
		return 
\b nil
\b0 ;\
	return self;\
\}\
\
- 
\b readCfromPath
\b0 :(const char *)path \{\
	NXStream *memstream;\
	\
	
\b memstream
\b0  = 
\b NXMapFile
\b0 (
\b path
\b0 , NX_READONLY);\
	if (memstream)\{\
		[self 
\b readC
\b0 : 
\b memstream
\b0 ];\
		
\b NXCloseMemory
\b0 (
\b memstream
\b0 , NX_FREEBUFFER);\
	\} else\
		return 
\b nil
\b0 ;\
	return self;\
\}\
- 
\b writeCtoPath
\b0 :(const char *)path \{\
	NXStream *memstream;\
	\
	
\b memstream
\b0  = 
\b NXOpenMemory
\b0 (
\b NULL
\b0 , 0, NX_WRITEONLY);\
	if (memstream) \{\
		[self 
\b writeC
\b0 :
\b memstream
\b0 ];\
		
\b NXSaveToFile
\b0 (memstream, 
\b path
\b0 );\
		
\b NXCloseMemory
\b0 (
\b memstream
\b0 , NX_FREEBUFFER);\
	\} else\
		return 
\b nil
\b0 ;\
	return self;\
\}\
\
//ппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп\
//	
\b Stream Operators
\b0 \
//\
- 
\b readASCII
\b0 : (
\b NXStream
\b0  *)s \{\
	return [self 
\b readText
\b0 :
\b s
\b0 ];\}\
- 
\b writeASCII
\b0 : (
\b NXStream
\b0  *)s \{\
	return [self 
\b writeASCII
\b0 :s 
\b from
\b0 :
\b 0
\b0  
\b to
\b0 :[self 
\b textLength
\b0 ]];\}\
- 
\b writeASCII
\b0 : (
\b NXStream
\b0  *)s 
\b from
\b0 :(
\b int
\b0 ) start 
\b to
\b0 :(
\b int
\b0 ) end \{\
	int 					k,N,cnt=0;\
	
\b NXRun
\b0  					*
\b curr
\b0 ;\
	
\b NXTextBlock
\b0 				*
\b currBlock
\b0 ;\
	int						
\b currentOffset
\b0 ,
\b targetOffset
\b0 ;\
	
\b id
\b0 						
\b compList
\b0 ;\
	\
	
\b N
\b0  = theRuns->chunk.
\b used
\b0 /sizeof(
\b NXRun
\b0 );\
	
\b curr
\b0  = theRuns->
\b runs
\b0 ;\
	
\b currBlock
\b0  = [self 
\b firstTextBlock
\b0 ];\
	
\b compList
\b0  = [[
\b List
\b0  alloc] 
\b init
\b0 ];\
	
\b currentOffset
\b0  = 
\b 0
\b0 ;	\
	for(k=0; (k < N) && (currentOffset < end); k++) \{\
\
		
\b targetOffset
\b0  = 
\b currentOffset
\b0  + curr->
\b chars
\b0 ;\
\
		if ((targetOffset > start) && (curr->
\b info
\b0 )) \{ \
			if ([curr->info 
\b respondsTo
\b0 :@selector(
\b writeASCIIRef:forView:
\b0 )]) \{\

\b 				NXPrintf
\b0 (s,"
\b [%d]
\b0 ", 
\b cnt++
\b0 );\
				[
\b compList
\b0  
\b addObject
\b0 :(curr->
\b info
\b0 )];\
			\}\
			if ([curr->info 
\b respondsTo
\b0 :@selector(
\b writeASCII:forView:
\b0 )])\{\
				[curr->info 
\b writeASCII
\b0 :s 
\b forView
\b0 :self];\
			\}\
		\}\
\
		// 
\i consume full blocks
\i0 \
		while (currBlock && (targetOffset >= currBlock->chars)) \{\
			\
			if ((targetOffset > start) && \
				(curr->
\b info
\b0  == nil) && \
				(
\b targetOffset 
\b0 > 
\b currentOffset
\b0 ))\
			 
\b 		\
					ASCIIEncoder
\b0 (s, currBlock->text + MAX(currentOffset,start),\
						MIN(end,currBlock->chars) - MAX(currentOffset,start));\
\
			targetOffset -= currBlock->chars;\
			start -= currBlock->chars;\
			end -= currBlock->chars;\
			currentOffset=0;\
			currBlock = currBlock->next;\
		\}\
	\
		// 
\i consume partial block
\i0 \
		if (currBlock)\
\
			if ((targetOffset > start) && \
				(curr->
\b info
\b0  == nil) && \
				(
\b targetOffset 
\b0 > 
\b currentOffset
\b0 ))\

\b \
				ASCIIEncoder
\b0 (s, currBlock->text + MAX(currentOffset,start),\
							MIN(end,targetOffset) - MAX(currentOffset,start));\
							\
		currentOffset=targetOffset;\
		curr++;\
	\}\
	\
	// 
\i compList
\i0 \
	
\b N
\b0 =[compList 
\b count
\b0 ];\
	if (
\b N
\b0 ) \{\

\b 		NXPrintf
\b0 (s,"
\b \\n\\nREFERENCES\\n\\n
\b0 ");\
		for (k=0; k < N; k++) \{\

\b 			NXPrintf
\b0 (s,"
\b [%d]\\t
\b0 ", 
\b k
\b0 );\
			[[compList 
\b objectAt
\b0 :
\b k
\b0 ] 
\b writeASCIIRef
\b0 :s 
\b forView
\b0 :self];\

\b 			NXPutc
\b0 (s,'
\b \\n
\b0 ');\
		\}\
	\}\
	[
\b compList
\b0  
\b free
\b0 ];\
	return self;\
\}\
\
- 
\b readC
\b0 : (
\b NXStream
\b0  *)s \{\
	return [self 
\b readText
\b0 :
\b s
\b0 ];\}\
- 
\b writeC
\b0 : (
\b NXStream
\b0  *)s \{\
	return [self 
\b writeC
\b0 :s 
\b from
\b0 :
\b 0
\b0  
\b to
\b0 :[self 
\b textLength
\b0 ]];\}\
- 
\b writeC
\b0 : (
\b NXStream
\b0  *)s 
\b from
\b0 :(
\b int
\b0 ) start 
\b to
\b0 :(
\b int
\b0 ) end \{\
	int 					k,N;\
	
\b NXRun
\b0  					*
\b curr
\b0 ;\
	
\b NXTextBlock
\b0 				*
\b currBlock
\b0 ;\
	int						
\b currentOffset
\b0 ,
\b targetOffset
\b0 ;\
	\
	
\b N
\b0  = theRuns->chunk.
\b used
\b0 /sizeof(
\b NXRun
\b0 );\
	
\b curr
\b0  = theRuns->
\b runs
\b0 ;\
	
\b currBlock
\b0  = [self 
\b firstTextBlock
\b0 ];\
	
\b currentOffset
\b0  = 
\b 0
\b0 ;	\
	for (k=0; k < N; k++) \{\
		if (curr->
\b info
\b0 ) \{ \
			if ([curr->info 
\b respondsTo
\b0 :@selector(
\b writeC:forView:
\b0 )])\{\
				[curr->info 
\b writeC
\b0 :s 
\b forView
\b0 :self];\
			\}\
		\}\

\i 		// encode the text corresponding to the run\
		// misson is to write (cumulative) curr->chars chars beginning\
		// at currentCount. boundaries may map onto > 1 block
\i0 \
		
\b targetOffset
\b0  = 
\b currentOffset
\b0  + curr->
\b chars
\b0 ;\
		// 
\i consume full blocks
\i0 \
		while ((currBlock) && (targetOffset >= (currBlock->chars))) \{\
			if (
\b !
\b0 (curr->
\b info
\b0 ))			        // 
\i throw annotated bits in bucket
\i0 \
				if(
\b targetOffset
\b0 >
\b currentOffset
\b0 ) // 
\i don't pass len=0 to encoder
\i0  \
					
\b NXWrite
\b0 (s, currBlock->text+currentOffset,\
								currBlock->chars - currentOffset);\
			targetOffset -= currBlock->chars;\
			currBlock = currBlock->next;\
			currentOffset=0;\
		\}\
		// 
\i consume partial block
\i0 \
		if (currBlock && (
\b !
\b0  curr->
\b info
\b0 ))   // 
\i throw annotated bits in bucket
\i0 \
			if(targetOffset>currentOffset) // 
\i don't pass len=0 to encoder
\i0  \
				
\b NXWrite
\b0 (s, currBlock->text + currentOffset,\
							targetOffset-currentOffset);\
		currentOffset=targetOffset;\
		curr++;\
	\}	\
	return self;\
\}\
\

\i @end
}
